#include"TextQuery.h"
#include "QueryResult.h"
#include "Util.h"
#include "Sentence.h"

#define DEBUG 0
vector<char> endOfWord{' ',',',';','-',':','.','\n','\"'};
vector<char> endOfSent{'.','!',';'};
vector<string> namePrefix{"Mr","Mrs","Miss","Ms"};

TextQuery::TextQuery(const string& filePath){
    ifstream infile(filePath);
    if(!infile){
        cout << "invaild file!" << endl;
        exit(-1);
    }
    file = make_shared<vector<Sentence>>();
    int curline = 1, startline = 1;
    string cont;
    char ch;
    bool newSent = false;

    auto loadSentDebug = [&](){
         if(DEBUG){
                cout << "new Sent loaded: "<< endl;
                cout << "line: " << startline << " ";
                cout << " idx: " << file->size() << " | ";
                cout << cont + ch ;
                cout << endl;
            }
    };

    while(infile.get(ch)){
        if(isupper(ch) && newSent == false){
            newSent = true;
            startline = curline;
        }
        else if(ch == '\n')
            curline++;
        else if(checkSent(cont) && newSent == true){
            extractWord(cont,file->size());
            loadSentDebug();
            file->push_back(Sentence(cont + ch,startline));
            cont = "";
            newSent = false;
        }
        if(newSent == true)
            cont += ch;
    }
    if(!cont.empty()){
        extractWord(cont,file->size());
        loadSentDebug();
        file->push_back(Sentence(cont,startline));
    }


}

QueryResult TextQuery::query(const string &inq) const{
	int cnt = 0;    //记录单词的出现次数
	string lowiq = tolowerStr(inq);  //将查询单词做大小写不敏感处理
	shared_ptr<std::set<int>> nodata(new std::set<int>);

    if(whichSent.find(lowiq) == whichSent.end()){
        cout << "no result" << endl;
        return QueryResult(lowiq,nodata,file);
    }
    auto loc = whichSent.find(lowiq);
    if(DEBUG){
        cout << " getQueryIdx: " << endl;
        for(int idx : loc->second){
            cout << idx << " ";
        }
        cout << endl;
    }
    shared_ptr<std::set<int>> data = make_shared<std::set<int>>(loc->second);
    return QueryResult(lowiq,data,file);
}   

void TextQuery::showText()
{
 
    for(Sentence st : *file){
        int line = st.line;
        printf("(line %4d) ",line);
        cout << st.contents;
        cout << endl;
    }
}


void TextQuery::extractWord(const string &str,int idx){
    auto hd = str.begin(), re = str.begin();
    while(re != str.end() ){
        if(!isalpha(*re)){
            hd++;
            re++;
        }
        else{
            while(isalpha(*re)){
                re++;
            }
            whichSent[tolowerStr(string(hd,re))].emplace(idx);
            hd = re;
        }
    }
}

bool TextQuery::checkSent(const string &str){
	if (std::find(namePrefix.begin(), namePrefix.end(), trim(str)) != namePrefix.end())	//避免把姓名前缀(句号结尾)当句子
		return false;
	if (str.empty())    //避免漏入空字符
		return false;
	if (std::find(endOfSent.begin(), endOfSent.end(), *str.rbegin()) != endOfSent.end())	//判断为句子的条件是看字符串尾元素是否属于句子终结符集合内任一元素
		return true;
	return false;
}